﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace RoadSystemTest
{
    /// <summary>
    /// Interaction logic for Road.xaml
    /// </summary>
    public partial class Road : UserControl, ITrafficObject
    {
        private Sites _site;
        public Sites Site
        {
            get { return _site; }
        }

        public Point Position {get; private set;}
        public Point GetPosition() { return Position; }
        public void SetPosition(Point pos) { Position = pos; RefreshPosition(); }

        private bool LanePointsVisible { get; set; }
        public void SetLanePointsVisible(bool visible) { LanePointsVisible = visible; UpdateLanePoints(); }
        public bool IsLanePointsVisible() { return LanePointsVisible; }

        private bool Selected { get; set; }

        public Road(Sites site, Point p)
        {
            InitializeComponent();
            Position = p;
            SetSite(site);
            
            ForwardLane = new Lane(this, _site, LaneTypes.Forward);
            ForwardLane.OnExitLane += lane_ExitLane;
            BackwardLane = new Lane(this, _site, LaneTypes.Backward);
            BackwardLane.OnExitLane += lane_ExitLane;

            RefreshPosition();

            SetLanePointsVisible(false);
        }

        private void RefreshPosition()
        {
            RoadTranslateTransform.X = Position.X;
            RoadTranslateTransform.Y = Position.Y;
            
            double xDelta = 150 - 40;
            double yDelta = 50 - 20;
            double margin = 10;
            double xTranslate = 150;
            double yTranslate = 50;
            // Sávok kezdőpontja a (0,0)-ponthoz relatívan
            Point fsPos = new Point { X = -xDelta + margin, Y = yDelta };
            Point fePos = new Point { X = xDelta - margin, Y = yDelta };
            Point bsPos = new Point { X = xDelta - margin, Y = -yDelta };
            Point bePos = new Point { X = -xDelta + margin, Y = -yDelta };
            // Sávok kezdőpontja a (150,50)-ponthoz (középponthoz) relatívan 
            fsPos.Translate(xTranslate, yTranslate);
            fePos.Translate(xTranslate, yTranslate);
            bsPos.Translate(xTranslate, yTranslate);
            bePos.Translate(xTranslate, yTranslate);
            // Sávok kezdőpontjainak rajzolása
            fsPos.ApplyToTranslateTransform(ForwardStart);
            fePos.ApplyToTranslateTransform(ForwardEnd);
            bsPos.ApplyToTranslateTransform(BackwardStart);
            bePos.ApplyToTranslateTransform(BackwardEnd);
            // A forgatást a (0,0) ponthoz képest kell csinálni, ezért visszatoljuk
            fsPos.Translate(-xTranslate, -yTranslate);
            fePos.Translate(-xTranslate, -yTranslate);
            bsPos.Translate(-xTranslate, -yTranslate);
            bePos.Translate(-xTranslate, -yTranslate);
            // A ffüggőleges útnál elforulnak a koordináták is
            fsPos.ApplyRotationTransform(RoadRotationTransform);
            fePos.ApplyRotationTransform(RoadRotationTransform);
            bsPos.ApplyRotationTransform(RoadRotationTransform);
            bePos.ApplyRotationTransform(RoadRotationTransform);
            // A (150,50) pontba (középpontba) be kell tolni
            //fsPos.Translate(xTranslate, yTranslate);
            //fePos.Translate(xTranslate, yTranslate);
            //bsPos.Translate(xTranslate, yTranslate);
            //bePos.Translate(xTranslate, yTranslate);
            // Belül automatikusan a parent Position-jéhez számolja
            ForwardLane.StartPosition = fsPos;
            ForwardLane.EndPosition = fePos;
            BackwardLane.StartPosition = bsPos;
            BackwardLane.EndPosition = bePos;
        }

        private void SetSite(Sites site)
        {
            _site = site;
            if (_site == Sites.Vertical)
            {
                RoadRotationTransform.Angle = -90;
            }
            else
            {
                RoadRotationTransform.Angle = 0;
            }
        }

        private void UpdateLanePoints()
        {
            ForwardStartRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
            ForwardEndRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
            BackwardStartRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
            BackwardEndRect.Visibility = LanePointsVisible ? Visibility.Visible : Visibility.Hidden;
        }

        public void Reset()
        {
            ForwardLane.RemoveAllCars();
            BackwardLane.RemoveAllCars();
        }

        public void Select()
        {
            if (Selected)
            {
                return;
            }
            Selected = true;

            RefreshBackground();
        }
        public void Deselect()
        {
            if (!Selected)
            {
                return;
            }
            Selected = false;
            RefreshBackground();
        }

        public bool IsSelected()
        {
            return Selected;
        }

        private void RefreshBackground()
        {
            if (Selected)
            {
                Panel.SetZIndex(this, 5);
                BackgroundRect.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF2D799C"));
            }
            else
            {
                Panel.SetZIndex(this, 4);
                BackgroundRect.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF686868"));
            }
        }

        public bool AddCar(Car car, bool isEastSouthFirstOnBothNull = false)
        {
            bool toEast = (ForwardLane.NextLane == null);
            bool toWest = (BackwardLane.NextLane == null);

            if (toEast && !toWest)
            {
                return BackwardLane.AddCar(car);
            }
            else if (toWest && !toEast)
            {
                return ForwardLane.AddCar(car);
            }
            return false;
        }

        public Road EastNorthRoad { get; private set; }
        public Road WestSouthRoad { get; private set; }

        public void ConnectEastNorthRoad(Road r)
        {
            // Az eredeti csatlakozás megszűntetése
            if (EastNorthRoad != null && EastNorthRoad.BackwardLane != null)
            {
                EastNorthRoad.BackwardLane.Connect(null);
            }
            EastNorthRoad = r;
            r.WestSouthRoad = this;
            if (r != null)
            {
                r.BackwardLane.Connect(BackwardLane);
                ForwardLane.Connect(r.ForwardLane);

                if (Site == Sites.Horizontal)
                {
                    r.SetPosition(new Point(Position.X + 200, Position.Y));
                }
                else
                {
                    r.SetPosition(new Point(Position.X, Position.Y - 200));
                }
            }
            else
            {
                ForwardLane.Connect(null);
            }
        }
        public void ConnectWestSouthRoad(Road r)
        {
            // Az eredeti csatlakozás megszűntetése
            if (WestSouthRoad != null && WestSouthRoad.ForwardLane != null)
            {
                WestSouthRoad.ForwardLane.Connect(null);
            }
            WestSouthRoad = r;
            r.EastNorthRoad = this;
            if (r != null)
            {
                r.ForwardLane.Connect(ForwardLane);
                BackwardLane.Connect(r.BackwardLane);

                if(Site == Sites.Horizontal)
                {
                    r.SetPosition(new Point(Position.X - 200, Position.Y));
                }
                else
                {
                    r.SetPosition(new Point(Position.X, Position.Y + 00));
                }
            }
            else
            {
                BackwardLane.Connect(null);
            }
        }

        private void lane_ExitLane(object sender, TrafficEventArgs e)
        {
            CarExitLane(e.car);
        }

        public Lane ForwardLane { get; private set; }
        public Lane BackwardLane { get; private set; }        

        private void ForwardLane_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            LaneClick(ForwardLane, new Point(ForwardStart.X, ForwardStart.Y), new Point(ForwardEnd.X, ForwardEnd.Y));
        }
        private void BackwardLane_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            LaneClick(BackwardLane, new Point(BackwardStart.X, BackwardStart.Y), new Point(BackwardEnd.X, BackwardEnd.Y));
        }

        public event TrafficEventHandler OnLaneClick;
        public void LaneClick(ILaneObject lane, Point start, Point end)
        {
            if (OnLaneClick != null)
                OnLaneClick(this, new TrafficEventArgs { lane = lane, laneStart = start, laneEnd = end });
        }

        public event TrafficEventHandler OnCarExitLane;
        public void CarExitLane(ICarObject car)
        {
            if (OnCarExitLane != null)
                OnCarExitLane(this, new TrafficEventArgs { car = car });
        }
    }
}
